# This is a BitKeeper generated patch for the following project: # Project Name: Linux kernel tree # This patch format is intended for GNU patch command version 2.5 or higher. # This patch includes the following deltas: # ChangeSet 1.1082 -> 1.1083 # include/linux/timex.h 1.5 -> 1.6 # kernel/time.c 1.12 -> 1.13 # kernel/timer.c 1.53 -> 1.54 # # The following is the BitKeeper ChangeSet Log # -------------------------------------------- # 03/05/14 davidm@tiger.hpl.hp.com 1.1083 # Add two hooks for high-precision time-interpolation. Based on patch by # Jes Sorensen. # -------------------------------------------- # diff -Nru a/include/linux/timex.h b/include/linux/timex.h --- a/include/linux/timex.h Thu May 15 13:42:12 2003 +++ b/include/linux/timex.h Thu May 15 13:42:12 2003 @@ -310,6 +310,13 @@ extern long pps_errcnt; /* calibration errors */ extern long pps_stbcnt; /* stability limit exceeded */ +/* + * Call-back for high precision timer sources to snapshot every time + * wall_jiffies is updated. + */ +extern void (*update_wall_time_hook)(long adjust_nsec); +extern void (*reset_wall_time_hook)(void); + #endif /* KERNEL */ #endif /* LINUX_TIMEX_H */ diff -Nru a/kernel/time.c b/kernel/time.c --- a/kernel/time.c Thu May 15 13:42:12 2003 +++ b/kernel/time.c Thu May 15 13:42:12 2003 @@ -35,8 +35,6 @@ */ struct timezone sys_tz; -extern unsigned long last_nsec_offset; - #if !defined(__alpha__) && !defined(__ia64__) /* @@ -77,9 +75,10 @@ if (get_user(value, tptr)) return -EFAULT; write_seqlock_irq(&xtime_lock); + + (*reset_wall_time_hook)(); xtime.tv_sec = value; xtime.tv_nsec = 0; - last_nsec_offset = 0; time_adjust = 0; /* stop active adjtime() */ time_status |= STA_UNSYNC; time_maxerror = NTP_PHASE_LIMIT; @@ -125,7 +124,7 @@ { write_seqlock_irq(&xtime_lock); xtime.tv_sec += sys_tz.tz_minuteswest * 60; - last_nsec_offset = 0; + (*update_wall_time_hook)(sys_tz.tz_minuteswest * 60 * NSEC_PER_SEC); write_sequnlock_irq(&xtime_lock); } @@ -381,7 +380,6 @@ txc->calcnt = pps_calcnt; txc->errcnt = pps_errcnt; txc->stbcnt = pps_stbcnt; - last_nsec_offset = 0; write_sequnlock_irq(&xtime_lock); do_gettimeofday(&txc->time); return(result); diff -Nru a/kernel/timer.c b/kernel/timer.c --- a/kernel/timer.c Thu May 15 13:42:12 2003 +++ b/kernel/timer.c Thu May 15 13:42:12 2003 @@ -65,6 +65,16 @@ typedef struct tvec_t_base_s tvec_base_t; +/* + * Hooks for using external high precision timers for the system clock. + * On systems where the CPU clock isn't synchronized between CPUs, + * it is necessary to use an external source such as an RTC to obtain + * precision in gettimeofday(). + */ +static void nop (void) { } +void (*update_wall_time_hook)(long delta_nsec) = (void (*) (void)) &nop; +void (*reset_wall_time_hook)(void) = &nop; + static inline void set_running_timer(tvec_base_t *base, struct timer_list *timer) { @@ -451,7 +461,6 @@ */ struct timespec xtime __attribute__ ((aligned (16))); struct timespec wall_to_monotonic __attribute__ ((aligned (16))); -unsigned long last_nsec_offset; /* Don't completely fail for HZ > 500. */ int tickadj = 500/HZ ? : 1; /* microsecs */ @@ -518,6 +527,7 @@ if (xtime.tv_sec % 86400 == 0) { xtime.tv_sec--; wall_to_monotonic.tv_sec++; + (*update_wall_time_hook)(-NSEC_PER_SEC); time_state = TIME_OOP; clock_was_set(); printk(KERN_NOTICE "Clock: inserting leap second 23:59:60 UTC\n"); @@ -528,6 +538,7 @@ if ((xtime.tv_sec + 1) % 86400 == 0) { xtime.tv_sec++; wall_to_monotonic.tv_sec--; + (*update_wall_time_hook)(NSEC_PER_SEC); time_state = TIME_WAIT; clock_was_set(); printk(KERN_NOTICE "Clock: deleting leap second 23:59:59 UTC\n"); @@ -643,25 +654,7 @@ delta_nsec += ltemp; } xtime.tv_nsec += delta_nsec; - - /* - * The whole point of last_nsec_offset is that it can be updated atomically and - * lock-free. Thus, arches that don't have __HAVE_ARCH_CMPXCHG probably can't use - * last_nsec_offset anyhow... --davidm 2003-Feb-11 - */ -#ifdef __HAVE_ARCH_CMPXCHG - if (last_nsec_offset > 0) { - unsigned long new, old; - - do { - old = last_nsec_offset; - if (old > delta_nsec) - new = old - delta_nsec; - else - new = 0; - } while (cmpxchg(&last_nsec_offset, old, new) != old); - } -#endif + (*update_wall_time_hook)(delta_nsec); /* update time interpolation */ } /* @@ -681,6 +674,7 @@ if (xtime.tv_nsec >= 1000000000) { xtime.tv_nsec -= 1000000000; xtime.tv_sec++; + (*update_wall_time_hook)(NSEC_PER_SEC); second_overflow(); } }